home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / formats / rle / rle.mss < prev    next >
Text File  |  1980-02-06  |  28KB  |  643 lines

  1. @Device(PostScript)
  2. @Make(Article)
  3. @comment[ TimesRoman kind of sucks, but we can assume most all PostScript
  4.           devices have it.
  5.           @style(FontFamily=NewCenturySchoolbook)
  6.         ]
  7. @style(FontFamily=TimesRoman)
  8. @style(Spacing=1)  @comment(1.1?)
  9. @Libraryfile(Mathematics10)
  10. @Modify(Description, LeftMargin +1.5inch, Indent -1.25inch)
  11.  
  12. @MajorHeading(Design of the Utah RLE Format)
  13.  
  14. @begin(Center)
  15. Spencer W. Thomas
  16. @blankSpace(1 line)
  17. University of Utah, Department of Computer Science
  18. @end(Center)
  19. @blankspace(1 inch)
  20. @Heading(Abstract)
  21. @begin(quotation)
  22. The Utah RLE (Run Length Encoded) format is designed to provide an efficient,
  23. device independent means of storing multi-level raster images.  Images of
  24. arbitrary size and depth can be saved.  The design of the format is
  25. presented, followed by descriptions of the library routines used to create
  26. and read RLE format files.
  27. @end(quotation)
  28.  
  29. @Section(Introduction)
  30.  
  31. The Utah RLE (Run Length Encoded) format is designed to provide an efficient,
  32. device independent means of storing multi-level raster images.  It is not
  33. designed for binary (bitmap) images.  It is built on several basic concepts.
  34. The central concept is that of a @i[channel].  A channel corresponds to a
  35. single color, thus there are normally a red channel, a green channel, and a
  36. blue channel.  Up to 255 color channels are available for use; one channel
  37. is reserved for "alpha" data.  Although the format supports arbitrarily deep
  38. channels, the current implementation is restricted to 8 bits per channel.
  39.  
  40. Image data is stored in an RLE file in a scanline form, with the data for
  41. each channel of the scanline grouped together.  Runs of identical pixel
  42. values are compressed into a count and a value.  However, sequences of
  43. differing pixels are also stored efficiently (not as a sequence of single
  44. pixel runs).
  45.  
  46. The file header contains a large amount of information about the image,
  47. including its size, the number of channels saved, whether it has an alpha
  48. channel, an optional color map, and comments.  The comments may be used to
  49. add arbitrary extra information to the saved image.
  50.  
  51. A subroutine interface has been written to allow programs to read and write
  52. files in the RLE format.  Two interfaces are available, one that completely
  53. interprets the RLE file and returns scanline pixel data, and one that returns
  54. a list of "raw" run and pixel data.  The second is more efficient, but more
  55. difficult to use, the first is easy to use, but slower.
  56.  
  57. The Utah RLE format has been used to save images from many sources, and to
  58. display saved images on many different displays and from many different
  59. computers.  
  60.  
  61. @Section(Description of RLE Format)
  62.  
  63. All data in the RLE file is treated as a byte stream.  Where quantities
  64. larger than 8 bits occur, they are written in PDP-11 byte order (low order
  65. byte first).
  66.  
  67. The RLE file consists of two parts, a header followed by scanline data.  The
  68. header contains general information about the image, while the scanline data
  69. is a stream of operations describing the image itself.
  70.  
  71. @SubSection(The Header)
  72.  
  73. @Begin(Figure)
  74. @Picture(size 3.5 inches, postscript="rle_head.ps")
  75. @Caption(RLE file header)
  76. @TAG(RLE header figure)
  77. @End(Figure)
  78.  
  79. The header has a fixed part and a variable part.  A diagram of the header is
  80. shown in Figure @Ref(RLE Header Figure).  The magic number identifies the
  81. file as an RLE file.  Following this are the coordinates of the lower left
  82. corner of the image and the size of the image in the X and Y directions.
  83. Images are defined in a first quadrant coordinate system (origin at the lower
  84. left, X increasing to the right, Y increasing up.)
  85. Thus, the image is enclosed in the rectangle
  86. @Begin(MathDisplay)
  87. [xpos, xpos + xsize - 1] X [ypos, ypos + ysize - 1].  
  88. @End(MathDisplay) 
  89. The position and size are 16 bit integer quantities; images up to 32K
  90. square may be saved (the sizes should not be negative).
  91.  
  92. A flags byte follows.  There are currently four flags defined:
  93. @Begin(Description)
  94. ClearFirst@\If this flag is set, the image rectangle should first be cleared
  95. to the background color (q.v.) before reading the scanline data.
  96.  
  97. NoBackground@\If this flag is set, no background color is supplied, and the
  98. ClearFirst flag should be ignored.
  99.  
  100. Alpha@\This flag indicates the presence of an "alpha" channel.  The alpha
  101. channel is used by image compositing software to correctly blend anti-aliased
  102. edges.   It is stored as channel -1 (255).
  103.  
  104. Comments@\If this flag is set, comments are present in the variable part of
  105. the header, immediately following the color map.
  106. @End(Description)
  107.  
  108. The next byte is treated as an unsigned 8 bit value, and indicates the number
  109. of color channels that were saved.  It may have any value from 0 to 254
  110. (channel 255 is reserved for alpha values).
  111.  
  112. The @i[pixelbits] byte gives the number of bits in each pixel.  The only value
  113. currently supported by the software is 8 (in fact, this byte is currently
  114. ignored when reading RLE files).  Pixel sizes taking more than one byte will
  115. be packed low order byte first.
  116.  
  117. The next two bytes describe the size and shape of the color map.  @i[Ncmap]
  118. is the number of color channels in the color map.  It need not be identical
  119. to @i[ncolors], but interpretation of values of @i[ncmap] different from
  120. @i[0], @i[1], or @i[ncolors] may be ambiguous, unless @i[ncolors] is @i[1].
  121. If @i[ncmap] is zero, no color map is saved.  @i[Cmaplen] is the log base 2
  122. of the length of each channel of the color map.  Thus, a value for
  123. @i[cmaplen] of 8 indicates a color map with 256 entries per channel.
  124.  
  125. Immediately following the fixed header is the variable part of the file
  126. header.  It starts with the background color.  The background color has
  127. @i[ncolors] entries; if necessary, it is filled out to an odd number of bytes
  128. with a filler byte on the end (since the fixed header is an odd number bytes
  129. long, this returns to a 16 bit boundary).
  130.  
  131. Following the background color is the color map, if present.  Color map
  132. values are stored as 16 bit quantities, left justified in the word.  Software
  133. interpreting the color map must apply a shift appropriate to the application
  134. or to the hardware being used.  This convention permits use of the color map
  135. without knowing the original output precision.  The channels of the map are
  136. stored in increasing numerical order (starting with channel 0), with the
  137. entries of each channel stored also in increasing order (starting with entry
  138. 0).  The color map entries for each channel are stored contiguously.
  139.  
  140. Comments, if present, follow the color map.  A 16 bit quantity giving the
  141. length of the comment block comes first.  If the length is odd, a filler byte
  142. will be present at the end, restoring the 16 bit alignment (but this byte is
  143. not part of the comments).  The comment block contains any number of
  144. null-terminated text strings.  These strings will conventionally be of the
  145. form "name=value", allowing for easy retrieval of specific information.
  146. However, there is no restriction that a given name appear only once, and a
  147. comment may contain an arbitrary string.  The intent of the comment block is
  148. to allow information to be attached to the file that is not specifically
  149. provided for in the RLE format.
  150.  
  151. @SubSection(The Scanline Data)
  152.  
  153. The scanline data consists of a sequence of operations, such as @i[Run],
  154. @i[SetChannel], and @i[Pixels], describing the actual image.  An image is
  155. stored starting at the lower left corner and proceeding upwards in order of
  156. increasing scanline number.  Each operation and its associated data takes up
  157. an even number of bytes, so that all operations begin on a 16 bit boundary.
  158. This makes the implementation more efficient on many architectures.
  159.  
  160. @Begin(Figure)
  161. @Picture(size=2 inches, postscript="rleops.ps")
  162. @Caption(RLE file operand formats)
  163. @Tag(Opcode format figure)
  164. @End(Figure)
  165.  
  166. Each operation is identified by an 8 bit opcode, and may have one or more
  167. operands.  Single operand operations fit into a single 16 bit word if the
  168. operand value is less than 256.  So that operand values are not limited to
  169. the range 0..255, each operation has a @i[long] variant, in which the byte
  170. following the opcode is ignored and the following word is taken as a 16 bit
  171. quantity.  The long variant of an opcode is indicated by setting the bit 0x40
  172. in the opcode (this allows for 64 opcodes, of which 6 have been used so far.)
  173. The two single operand formats are shown pictorially in Figure @Ref(Opcode
  174. format Figure).
  175.  
  176. The individual operations will now be discussed in detail.  The descriptions
  177. are phrased in terms of the actions necessary to interpret the file.  Three
  178. indices are necessary: the @i[current channel], the @i[scanline number], and
  179. the @i[pixel index].  The @i[current channel] is the channel to which data
  180. operations apply.  The @i[scanline number] is just the Y position of the
  181. scanline in the image.  The @i[pixel index] is the X position of the pixel
  182. within the scanline.  The operations are:
  183.  
  184. @Begin(Description)
  185. SkipLines@\Increment the @i[scanline number] by the operand value.  This
  186. operation terminates the current scanline.  The @i[pixel index] should be reset
  187. to the xpos value from the header.
  188.  
  189. SetColor@\Set the @i[current channel] to the operand value.  This operation
  190. does not have a long variant.  Note that an operand value of 255 will be
  191. interpreted as a @math[-1], indicating the alpha channel.  All other operand
  192. values are positive.  The @i[pixel index] is reset to the xpos value.
  193.  
  194. SkipPixels@\Skip over pixels in the current scanline.  Increment @i[pixel
  195. index] by the operand value.  Pixels skipped will be left in the background
  196. color.
  197.  
  198. PixelData@\Following this opcode is a sequence of pixel values.  The length
  199. of the sequence is given by the operand value.  If the length of the sequence
  200. is odd, a filler byte is appended.  Pixel values are inserted into the
  201. scanline in increasing X order.  The @i[pixel index] is incremented by the
  202. sequence length.
  203.  
  204. Run@\This is the only two operand opcode.  The first operand is the length
  205. (@i[N]) of the run.  The second operand is the pixel value, followed by a
  206. filler byte if necessary@Footnote(E.g., a 16 bit pixel value would not need a
  207. filler byte.).  The next @i[N] pixels in the scanline are set to
  208. the given pixel value.  The @i[pixel index] is incremented by @i[N], to point
  209. to the pixel following the run.
  210.  
  211. EOF@\This opcode has no operand, and indicates the end of the RLE file.  It
  212. is provided so that RLE files may be concatenated together and still be
  213. correctly interpreted.  It is not required, a physical end of file will also
  214. indicate the end of the RLE data.
  215. @End(Description)
  216.  
  217. @SubSection(Subroutine Interface)
  218.  
  219. Two similar subroutine interfaces are provided for reading and writing files
  220. in the RLE format.  Both read or write a scanline worth of data at a time.  A
  221. simple "row" interface communicates in terms of arrays of pixel values.  It
  222. is simple to use, but slower than the "raw" interface, which uses a list of
  223. "opcode" values as its communication medium.
  224.  
  225. In both cases, the interface must be initialized by calling a setup function.
  226. The two types of calls may be interleaved; for example, in a rendering
  227. program, the background could be written using the "raw" interface, while
  228. scanlines containing image data could be converted with the "row" interface.
  229. The package allows multiple RLE streams to be open simultaneously, as is
  230. necessary for use in a compositing tool, for example.  All data relevant to a
  231. particular RLE stream is contained in a "globals" structure.
  232.  
  233. The globals structure echoes the format of the RLE header.
  234. The fields are described below:
  235. @Begin(Description)
  236. dispatch@\The RLE creation routines are capable of writing various types
  237. of output files in addition to RLE.  This value is an index into a dispatch
  238. table.  This value is initialized by @i[sv_setup].
  239.  
  240. ncolors@\The number of color channels in the output file.  Up to this many
  241. color channels will be saved, depending on the values in the channel bitmap
  242. (see below).
  243.  
  244. bg_color@\A pointer to an array of @i[ncolors] integers containing the
  245. background color.
  246.  
  247. alpha@\If this is non-zero, an alpha channel will be saved.  The presence or
  248. absence of an alpha channel has no effect on the value in @i[ncolors].
  249.  
  250. background@\Indicates how to treat background pixels.  It has the following
  251. values:
  252. @Begin(Description, LeftMargin +.5inch, Indent -.5inch)
  253. 0@\Save all pixels, the background color is ignored.
  254.  
  255. 1@\Save only non-background pixels, but don't set the "clear screen" bit.
  256. This indicates "overlay" mode, a cheap form of compositing (but see note
  257. below about this.)
  258.  
  259. 2@\Save only non-background pixels, clear the screen to the background color
  260. before restoring the image.
  261. @End(Description)
  262.  
  263. xmin, xmax, ymin, ymax@\Inclusive bounds of the image region being saved.
  264.  
  265. ncmap@\Number of channels of color map to be saved.  The color map will not
  266. be saved if this is 0.
  267.  
  268. cmaplen@\Log base 2 of the number of entries in each channel of the color
  269. map.
  270.  
  271. cmap@\Pointer to an array containing the color map.  The map is saved in
  272. "channel major" order.  Each entry in the map is a 16 bit value with the
  273. color value left justified in the word.  If this pointer is NULL, no color
  274. map will be saved.
  275.  
  276. comments@\Pointer to an array of pointers to strings.  The array is
  277. terminated by a NULL pointer (like @i[argv] or @i[envp]).  If this pointer is
  278. NULL or if the first pointer it points to is NULL, comments will not be saved.
  279.  
  280. fd@\File (FILE *) pointer to be used for writing or reading the RLE file.
  281.  
  282. bits@\A bitmap containing 256 bits.  A channel will be saved (or retrieved)
  283. only if the corresponding bit is set in the bitmap.  The alpha channel
  284. corresponds to bit 255.  The bitmap allows an application to easily ignore
  285. color channel data that is irrelevant to it.
  286. @End(Description)
  287. The globals structure also contains private data for use by the RLE reading
  288. and writing routines; data that must be maintained between calls, but that 
  289. applies to each stream separately.
  290.  
  291. @SubSection(Writing RLE files)
  292.  
  293. To create a run-length encoded file, one first initializes a globals
  294. structure with the relevant information about the image, including the output
  295. file descriptor.  The output file should be open and empty.
  296. Then one calls @i[sv_setup]:
  297. @Begin(ProgramExample)
  298. sv_setup( RUN_DISPATCH, &globals );
  299. @End(ProgramExample) 
  300. This writes the file header and initializes the private portions of the
  301. global data structure for use by the RLE file writing routines.
  302.  
  303. The image data must be available or expressible in a scanline order (with the
  304. origin at the bottom of the screen).  After each scanline is computed, it is
  305. written to the output file by calling one of @i[sv_putrow] or @i[sv_putraw].
  306. If a vertical interval of the image has no data, it may be skipped by calling
  307. sv_skiprow:
  308. @Begin(ProgramExample)
  309. /* Skip nrow scanlines */
  310. sv_skiprow( &globals, nrow );
  311. @End(ProgramExample)
  312.  
  313. If the image data for a scanline is available as an array of pixel values,
  314.  @i[sv_putrow] should be used to write the data to the output file.  As an
  315. example, let us assume that we have a 512 pixel long scanline, with three
  316. color channels and no alpha data.  We could call @i[sv_putrow] as follows:
  317. @Begin(ProgramExample)
  318. rle_pixel scandata[3][512], *rows[3];
  319. int i;
  320.  
  321. for ( i = 0; i < 3; i++ )
  322.     rows[i] = scandata[i];
  323. sv_putrow( rows, 512, &globals );
  324. @End(ProgramExample)
  325. Note that @i[sv_putrow] is passed an array of pointers to vectors of pixels.
  326. This makes it easy to pass arbitrarily many, and to specify values of
  327. @i[rowlen] different from the size of (e.g.) the @i[scandata] array.
  328.  
  329. The first element of each row of pixels is the pixel at the @i[xmin] location
  330. in the scanline.  Therefore, when saving only part of an image, one must be
  331. careful to set the @i[rows] pointers to point to the correct pixel in the
  332. scanline. 
  333.  
  334. If an alpha channel is specified to be saved, things get a little more
  335. complex.  Here is the same example, but now with an alpha channel being
  336. saved.
  337. @Begin(ProgramExample)
  338. rle_pixel scandata[3][512], 
  339.       alpha[512], *rows[4];
  340. int i;
  341.  
  342. rows[0] = alpha;
  343. for ( i = 0; i < 3; i++ )
  344.     rows[i+1] = scandata[i];
  345. sv_putrow( rows+1, 512, &globals );
  346. @End(ProgramExample)
  347. The @i[sv_putrow] routine expects to find the pointer to the alpha channel at
  348. the @math[-1] position in the rows array.  Thus, we pass a pointer to
  349.  @i<rows[1]> and put the pointer to the alpha channel in @i<rows[0]>.
  350.  
  351. Finally, after all scanlines have been written, we call @i[sv_puteof] to
  352. write an @i[EOF] opcode into the file.  This is not strictly necessary, since a
  353. physical end of file also indicates the end of the RLE data, but it is a good
  354. idea.
  355.  
  356. Here is a skeleton of an application that uses @i[sv_putrow] to save an
  357. image is shown in Figure @Ref(sv_putrow example figure).  This example
  358. uses the default values supplied in the globals variable @i[sv_globals],
  359. modifying it to indicate the presence of an alpha channel.
  360. @Begin(Figure, Above 99, Columns 1)
  361. @Begin(ProgramExample)
  362. #include <svfb_global.h>
  363.  
  364. main()
  365. {
  366.     rle_pixel scanline[3][512], alpha[512], *rows[4];
  367.     int y, i;
  368.  
  369.     /* Most of the default values in sv_globals are ok */
  370.     /* We do have an alpha channel, though */
  371.     sv_globals.sv_alpha = 1;
  372.     SV_SET_BIT( sv_globals, SV_ALPHA );
  373.  
  374.     rows[0] = alpha;
  375.     for ( i = 0; i < 3; i++ )
  376.         rows[i+1] = scanline[i];
  377.  
  378.     sv_setup( RUN_DISPATCH, &sv_globals );
  379.  
  380.     /* Create output for 512 x 480 (default size) display */
  381.     for ( y = 0; y < 480; y++ )
  382.     {
  383.         mk_scanline( y, scanline, alpha );
  384.         sv_putrow( rows, 512, &sv_globals );
  385.     }
  386.     sv_puteof( &sv_globals );
  387. }
  388. @End(ProgramExample)
  389. @Caption(Example of use of sv_putrow)
  390. @Tag(Sv_putrow example figure)
  391. @End(Figure)
  392.  
  393. Using @i[sv_putraw] is more complicated, as it takes arrays of @i[rle_op]
  394. structures instead of just pixels.  If the data is already available in
  395. something close to this form, however, @i[sv_putraw] will run much more
  396. quickly than @i[sv_putrow].  An @i[rle_op] is a structure with the following
  397. contents:
  398. @Begin(Description)
  399. opcode@\The type of data.  One of @i[ByteData] or @i[RunData].
  400.  
  401. xloc@\The X location within the scanline at which this data begins.
  402.  
  403. length@\The length of the data.  This is either the number of pixels that are
  404. the same color, for a run, or the number of pixels provided as byte data.
  405.  
  406. pixels@\A pointer to an array of pixel values.  This field is used only for
  407. the @i[ByteData] opcode.
  408.  
  409. run_val@\The pixel value for a @i[RunData] opcode.
  410. @End(Description)
  411.  
  412. Since there is no guarantee that the different color channels will require
  413. the same set of @i[rle_ops] to describe their data, a separate count must be
  414. provided for each channel.  Here is a sample call to @i[sv_putraw]:
  415. @Begin(ProgramExample)
  416. int nraw[3];    /* Length of each row */
  417. rle_op *rows[3];/* Data pointers */
  418. sv_putraw( rows, nraw, &globals );
  419. @End(ProgramExample)
  420. A more complete example of the use of @i[sv_putraw] will be given in
  421. connection with the description of @i[rle_getraw], below.
  422.  
  423. Calls to @i[sv_putrow] and @i[sv_putraw] may be freely intermixed, as
  424. required by the application.
  425.  
  426. @SubSection(Reading RLE Files)
  427.  
  428. Reading an RLE file is much like writing one.  An initial call to a setup
  429. routine reads the file header and fills in the @i[globals] structure.
  430. Then, a scanline at a time is read by calling @i[rle_getrow] or
  431. @i[rle_getraw].
  432.  
  433. The calling program is responsible for opening the input file.  A call to
  434.  @i[rle_get_setup] will then read the header information and fill in the
  435. supplied globals structure.  The return code from @i[rle_get_setup] indicates
  436. a variety of errors, such as the input file not being an RLE file, or
  437. encountering an EOF while reading the header.
  438.  
  439. Each time @i[rle_getrow] is called, it fills in the supplied scanline buffer
  440. with one scanline of image data and returns the Y position of the scanline
  441. (which will be one greater than the previous time it was called).  Depending
  442. on the setting of the @i[background] flag, the scanline buffer may or may
  443. not be cleared to the background color on each call.  If it is not
  444. (@i[background] is 0 or 1), and if the caller does not clear the buffer
  445. between scanlines, then a "smearing" effect will be seen, if some pixels from
  446. previous scanlines are not overwritten by pixels on the current scanline.
  447. Note that if @i[background] is 0, then no background color was supplied,
  448. and setting @i[background] to 2 to try to get automatic buffer clearing
  449. will usually cause a segmentation fault when @i[rle_getrow] tries to get the
  450. background color through the @i[bg_color] pointer.
  451.  
  452. Figure @Ref[RLE_getrow Figure] shows an example of the use of @i[rle_getrow].
  453. Note the dynamic allocation of scanline storage space, and compensation for
  454. presence of an alpha channel.  A subroutine, @i[rle_row_alloc], is available
  455. that performs the storage allocation automatically.  It is described below.
  456. If the alpha channel were irrelevant, the macro @i[SV_CLR_BIT] could be used
  457. to inhibit reading it, and no storage space would be needed for it.
  458. @Begin(Figure, Above 99, Columns 1)
  459. @Begin(ProgramExample)
  460. /* An example of using rle_getrow */
  461. /* Scanline pointer */
  462. rle_pixel ** scan;
  463. int i;
  464.  
  465. /* Read the RLE file from stdin */
  466. rle_get_setup( &globals );
  467.  
  468. /* Allocate enough space for scanline data, including alpha channel */
  469. /* (Should check for non-zero return, indicating a malloc error) */
  470. rle_row_alloc( &globals, &scan );
  471.  
  472. /* Read scanline data */
  473. while ( (y = rle_getrow( &globals, stdin, scan ) <= globals.sv_ymax )
  474.     /* Use the scanline data */;
  475.  
  476. @End(ProgramExample)
  477. @Caption(Example of rle_getrow use.)
  478. @Tag(rle_getrow figure)
  479. @End(Figure)
  480.  
  481. The function @i[rle_getraw] is the inverse of @i[sv_putraw].  When called, it
  482. fills in the supplied buffer with raw data for a single scanline.  It returns
  483. the scanline @i[y] position, or @math[2@+(15)] to indicate end of file.  It is
  484. assumed that no image will have more than @math[2@+(15)-1] scanlines.  A
  485. complete program (except for error checking) that reads an RLE file from
  486. standard input and produces a negative image on standard output is shown in
  487. Figure @Ref(Negate program figure).
  488.  
  489. @Begin(FullPageFigure, Columns 1)
  490. @Begin(ProgramExample)
  491. #include <stdio.h>
  492. #include <svfb_global.h>
  493. #include <rle_getraw.h>
  494.  
  495. main()
  496. {
  497.     struct sv_globals in_glob, out_glob;
  498.     rle_op ** scan;
  499.     int * nraw, i, j, c, y, newy;
  500.  
  501.     in_glob.svfb_fd = stdin;
  502.     rle_get_setup( &in_glob );
  503.     /* Copy setup information from input to output file */
  504.     out_glob = in_glob;
  505.     out_glob.svfb_fd = stdout;
  506.  
  507.     /* Get storage for calling rle_getraw */
  508.     rle_raw_alloc( &in_glob, &scan, &nraw );
  509.  
  510.     /* Negate background color! */
  511.     if ( in_glob.sv_background )
  512.     for ( i = 0; i < in_glob.sv_ncolors; i++ )
  513.         out_glob.sv_bg_color[i] = 255 - out_glob.sv_bg_color[i];
  514.  
  515.     /* Init output file */
  516.     sv_setup( RUN_DISPATCH, &out_glob );
  517.  
  518.     y = in_glob.sv_ymin;
  519.     while ( (newy = rle_getraw( &in_glob, scan, nraw )) != 32768 ) {
  520.     /* If > one line skipped in input, do same in output */
  521.     if ( newy - y > 1 )
  522.         sv_skiprow( &out_glob, newy - y );
  523.     y = newy;
  524.     /* Map all color channels */
  525.     for ( c = 0; c < out_glob.sv_ncolors; c++ )
  526.         for ( i = 0; i < nraw[c]; i++ )
  527.         switch( scan[c][i].opcode ) {
  528.         case RRunDataOp:
  529.             scan[c][i].u.run_val = 255 - scan[c][i].u.run_val;
  530.             break;
  531.         case RByteDataOp:
  532.             for ( j = 0; j < scan[c][i].length; j++ )
  533.             scan[c][i].u.pixels[j] =
  534.                 255 - scan[c][i].u.pixels[j];
  535.             break;
  536.         }
  537.     sv_putraw( scan, nraw, &out_glob );
  538.     /* Free raw data */
  539.     rle_freeraw( &in_glob, scan, nraw );
  540.     }
  541.     sv_puteof( &out_glob );
  542.  
  543.     /* Free storage */
  544.     rle_raw_free( &in_glob, scan, nraw );
  545. }
  546.  
  547. @End(ProgramExample)
  548. @Caption(Program to produce a negative of an image)
  549. @Tag(Negate program figure)
  550. @End(FullPageFigure)
  551.  
  552. The functions @i[rle_row_alloc] and @i[rle_raw_alloc] simplify allocation of
  553. buffer space for use by the rle routines.  Both use a supplied globals
  554. structure to determine how many and which channels need buffer space, as well
  555. as the size of the buffer for each scanline.  The returned buffer pointers
  556. will be adjusted for the presence of an alpha channel, if it is present.
  557. Buffer space for pixel or @i[rle_op] data will be allocate only for those
  558. channels that have bits set in the channel bitmap.  The buffer space may be
  559. freed by calling @i[rle_row_free] or @i[rle_raw_free], respectively.
  560.  
  561. @Section(Comments, issues, and directions)
  562.  
  563. Some comments on the file format and current subroutine implementation:
  564. @Begin[Itemize]
  565. The background color for the alpha channel is always 0.
  566.  
  567. All channels must have the same number of bits.  This could be a problem when
  568. saving, e.g., Z values, or if more than 8 bits of precision were desired for
  569. the alpha channel.
  570.  
  571. Pixels are skipped (by @i[sv_putrow]) only if all channel values of the pixel
  572. are equal to the corresponding background color values.
  573.  
  574. The current Implementation of @i[sv_putrow] skips pixels only if at least 2
  575. adjacent pixels are equal to the background.  The SkipPixels operation is
  576. intended for efficiency, not to provide cheap compositing.
  577.  
  578. Nothing forces the image data to lie within the bounds declared in the
  579. header.  However, @i[rle_getrow] will not write outside these bounds, to
  580. prevent core dumps.  No such protection is provided by @i[rle_getraw].
  581.  
  582. Images saved in RLE are usually about 1/3 their original size (for an
  583. "average" image).  Highly complex images may end up slightly larger than
  584. they would have been if saved by the trivial method.
  585. @End[Itemize]
  586.  
  587. We have not yet decided how pixels with other than 8 bits should be packed
  588. into the file.  To keep the file size down, one would like to pack
  589. @i[ByteData] as tightly as possible.  However, for interpretation speed, it
  590. would probably be better to save one value in each
  591. @math[(pixelbits+7)/8] bytes.
  592.  
  593. Some proposed enhancements include:
  594. @begin[Itemize]
  595. A "ramp" opcode.  This specifies that pixel values should be linearly ramped
  596. between two values for a given number of pixels in the scanline.  This opcode
  597. would be difficult to generate from an image, but if an application knew it
  598. was generating a ramp, it could produce significant file size savings (e.g.
  599. in Gouraud shaded images).
  600.  
  601. Opcodes indicating that the current scanline is identical to the previous, or
  602. that it differs only slightly (presumably followed by standard opcodes
  603. indicating the difference).  Detection of identical scanlines is easy,
  604. deciding that a scanline differs slightly enough to warrant a differential
  605. description could be difficult.  In images with large areas with little
  606. change, this could produce size savings@Footnote[This
  607. suggestion was inspired by a description of the RLE format used at Ohio State
  608. University.]
  609. @End[Itemize]
  610.  
  611. The subroutine library is still missing some useful functions.  Some proposed
  612. additions are:
  613. @Begin(Itemize)
  614. Conversion from "raw" to "row" format, and back.  One could then view
  615.  @i[sv_putrow] as being a "raw" to "row" conversion followed by a call to
  616.  @i[sv_putraw], and @i[rle_getrow] as a call to @i[rle_getraw] followed by
  617. "row" to "raw" conversion.
  618.  
  619. A function to merge several channels of "raw" data into a single channel.
  620. For example, this would take separate red, green, and blue channels and
  621. combine them into a single RGB channel.  This would be useful for RLE
  622. interpretation on devices that do not easily support the separate channel
  623. paradigm, while preserving the efficiency of the "raw" interface.  It could
  624. also be used to increase the efficiency of a compositing program.
  625. @End(Itemize)
  626.  
  627. The Utah RLE format has developed and matured over a period of about six
  628. years, and has proven to be versatile and useful for a wide variety of
  629. applications that require image transmittal and storage.  It provides a
  630. compact, efficiently interpreted image storage capability.  We expect to see
  631. continued development of capabilities and utility, but expect very little
  632. change in the basic format.
  633.  
  634.  
  635. @section(Acknowledgments)
  636. This work was supported in part by the National Science Foundation
  637. (DCR-8203692 and DCR-8121750), the Defense Advanced Research Projects Agency
  638. (DAAK11-84-K-0017), the Army Research Office (DAAG29-81-K-0111), and
  639. the Office of Naval Research (N00014-82-K-0351).
  640. All opinions, findings, conclusions or recommendations expressed in this
  641. document are those of the authors and do not necessarily reflect the views of
  642. the sponsoring agencies.
  643.